package ch.cryptobox.filehandles;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;

import org.acplt.oncrpc.OncRpcException;

import ch.cryptobox.nfsError.ReadWriteException;
import ch.cryptobox.serivces.MultiServerSynchronizationService;


public class MultiFileHandle implements FileHandleI {
	private final ArrayList< FileHandleI > handles = new ArrayList< FileHandleI >();
	private final MultiServerSynchronizationService service;
	

	
	
	public MultiFileHandle(final MultiServerSynchronizationService service) {
		this.service = service;
	}
	
	public void addHandle(final FileHandleI handle) {
		handles.add(handle);
	}
	
	public ArrayList< FileHandleI > getHandles() {
		return handles;
	}
	
	
	@Override
	public boolean isDirectory() {
		return handles.get(0).isDirectory();
	}

	@Override
	public byte[] download() {
		try {
			return service.readFile(this);
		} catch (OncRpcException | IOException | ReadWriteException e) {
			e.printStackTrace();
			return null;
		}
	}

	@Override
	public FileHandleI getFile(final String relPath) {
		final MultiFileHandle handle = new MultiFileHandle(service);

		for(final FileHandleI h : handles) {
			final FileHandleI file = h.getFile(relPath);
			if(file == null) {
				return null;
			}
			
			handle.addHandle(file);
		}
		
		
		return handle;
	}

	@Override
	public FileHandleI getDirectory(final String relPath) {
		final MultiFileHandle handle = new MultiFileHandle(service);

		for(final FileHandleI h : handles) {
			final FileHandleI file = h.getDirectory(relPath);
			if(file == null) {
				return null;
			}
			
			handle.addHandle(file);
		}
	
		return handle;
	}

	@Override
	public boolean isRoot() {
		return handles.get(0).isRoot();
	}

	//Not really efficient but it'll do
	@Override
	public ArrayList<FileHandleI> getFiles() {
		if(!isDirectory())
			return new ArrayList<FileHandleI>();
		
		final ArrayList<FileHandleI> files = new ArrayList<FileHandleI>();
		final ArrayList<ArrayList<FileHandleI>> allRemoteFiles = new ArrayList<ArrayList<FileHandleI>>();
		
		//TODO multithreaded
		for(final FileHandleI h: handles) {
			final ArrayList<FileHandleI> subFiles = h.getFiles();
			if(subFiles == null) 
				return new ArrayList<FileHandleI>();
			
			allRemoteFiles.add(subFiles);
		}
		if(allRemoteFiles.isEmpty() || allRemoteFiles.get(0).isEmpty() ) 
			return new ArrayList<FileHandleI>();
		
		for(int i = 0; i < allRemoteFiles.get(0).size(); ++i) {
			final MultiFileHandle mHandle = new MultiFileHandle(service);
		
			for(int j = 0; j < allRemoteFiles.size(); ++j) {
				if(allRemoteFiles.get(j).size() != allRemoteFiles.get(0).size()) {
					System.out.println(MultiFileHandle.class.getName() + ".getFiles();\nRemote servers are not synched with each other. Skipping all. checked(" + allRemoteFiles.get(0).get(i).getName() + ")");
					return new  ArrayList<FileHandleI>(); //If the file is not in all servers then it is not supported by the service
					
				}
				mHandle.addHandle(allRemoteFiles.get(j).get(i));
			}
			files.add(mHandle);
		}
		
		
		return files;
	}

	@Override
	public FileHandleI getParent() {
		final MultiFileHandle parent = new MultiFileHandle(service);
		for(final FileHandleI h: handles) {
			final FileHandleI file = h.getParent();
			if(file == null)
				return null;	
			parent.addHandle(file);
		}
		return parent;
	}

	@Override
	public String getName() {
		return handles.get(0).getName();
	}

	@Override
	public String getPath() {
		return handles.get(0).getPath();
	}


	@Override
	public Date getDate() {
		return handles.get(0).getDate();
	}

	
	@Override
	public String toString() {
		return handles.get(0).toString();
	}
}
